package com.yunban.project.template.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunban.project.template.mapper.TemplateMapper;
import com.yunban.project.template.model.domain.*;
import com.yunban.project.template.model.dto.TemplateReq;
import com.yunban.project.template.model.dto.TemplateSearchReq;
import com.yunban.project.template.model.vo.StyleResp;
import com.yunban.project.template.model.vo.TemplateGroupResp;
import com.yunban.project.template.model.vo.TemplateResp;
import com.yunban.project.template.model.vo.TypeResp;
import com.yunban.project.template.service.*;
import jakarta.annotation.Resource;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.exception.BusinessException;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import org.apache.velocity.runtime.directive.Foreach;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author: lijiajun
 * @date: 2024-11-06
 * @version: 1.0
 */
@Service
public class TemplateServiceImpl extends ServiceImpl<TemplateMapper, Template> implements TemplateService {

    @Resource
    private TemplateStyleService templateStyleService;

    @Resource
    private TypeService typeService;

    @Resource
    private StyleService styleService;

    @Resource
    private TemplateGroupMapService templateGroupMapService;

    @Resource
    private TemplateGroupService templateGroupService;


    @Resource
    private TemplateCollectService templateCollectService;

    @Override
    public Template findById(long id) {
        Template template = this.getById(id);
        if (ObjectUtils.isEmpty(template)) {
            throw new BusinessException("模板信息不存在");
        }
        return template;
    }

    @Override
    public List<Template> findByUserId(long userId) {
        LambdaQueryWrapper<Template> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Template::getCreatedBy, userId);
        return this.list(wrapper);
    }

    @Override
    public PageResult<TemplateResp> search(TemplateSearchReq req) {
        LambdaQueryWrapper<Template> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(req.getName())) {
            wrapper.like(Template::getName, req.getName());
        }
        if (null != req.getBlockTypeId()) {
            wrapper.eq(Template::getBlockTypeId, req.getBlockTypeId());
        }
        if (!CollectionUtils.isEmpty(req.getStyleIds())) {
            // 查询包含 req.getStyleIds().size() 的所有模板IDS
            List<TemplateStyle> templateStyleList = this.templateStyleService.findByStyleIdIn(req.getStyleIds());
            // 使用stream流的方式 将 templateStyleList 按 templateId 进行分组
            Map<Long, List<TemplateStyle>> templateStyleGroupMap = templateStyleList.stream().collect(Collectors.groupingBy(TemplateStyle::getTemplateId));
            // 遍历循环 templateStyleGroupMap 取出 每组长度大于等于req.getStyleIds().size() 的模板ID
            List<Long> templateIds = new ArrayList<>();
            for (Map.Entry<Long, List<TemplateStyle>> entry : templateStyleGroupMap.entrySet()) {
                // 精准查询
//                if (entry.getValue().size() >= req.getStyleIds().size()) {
                // TODO 2024-11-24 模糊查询
                templateIds.add(entry.getKey());
//                }
            }
            // in 查询
            if (CollectionUtils.isEmpty(templateIds)) {
                templateIds.add(-1L);
            }
            wrapper.in(Template::getId, templateIds);
        }
        Page<Template> page = this.page(SmartPageUtil.convert2PageQuery(req), wrapper);
        PageResult<TemplateResp> result = SmartPageUtil.convert2PageResult(page, TemplateResp.class);
        // 获取所有的模板类型MAP
        List<TypeResp> typeList = SmartPageUtil.convert(this.typeService.list(), TypeResp.class);
        // typeList to map
        Map<Long, TypeResp> typeMap = typeList.stream().collect(Collectors.toMap(TypeResp::getId, Function.identity()));
        // 获取风格列表
        List<StyleResp> styleList = SmartPageUtil.convert(this.styleService.list(), StyleResp.class);
        // 将 styleList 转为map
        Map<Long, StyleResp> styleMap = styleList.stream().collect(Collectors.toMap(StyleResp::getId, Function.identity()));
        // 获取所有的模板风格映射信息
        List<TemplateStyle> templateStyleList = this.templateStyleService.list();
        // 获取所有模板组map
        List<TemplateGroupMap> templateGroupMapList = this.templateGroupMapService.list();
        // 获取所有模板组列表
        List<TemplateGroup> templateGroupList = this.templateGroupService.list();
        Map<Long, TemplateGroup> templateGroupMap = templateGroupList.stream().collect(Collectors.toMap(TemplateGroup::getId, Function.identity()));
        // 获取我的收藏记录
        long userId = SmartRequestUtil.getUserId();
        List<Long> userCollectList = this.templateCollectService.getUserCollectList(userId);
        result.getList().forEach(items -> {
            items.setBlockType(typeMap.get(items.getBlockTypeId()));
            templateStyleList.forEach(templateStyle -> {
                if (items.getId().equals(templateStyle.getTemplateId())) {
                    // 获取风格信息
                    StyleResp styleResp = styleMap.get(templateStyle.getStyleId());
                    if (!ObjectUtils.isEmpty(styleResp)) {
                        items.getStyleList().add(styleResp);
                    }
                }
            });
            for (TemplateGroupMap groupMap : templateGroupMapList) {
                if (items.getId().equals(groupMap.getTemplateId())) {
                    TemplateGroup templateGroup = templateGroupMap.get(groupMap.getGroupId());
                    if (!ObjectUtils.isEmpty(templateGroup)) {
                        items.getGroupList().add(SmartPageUtil.convert(templateGroup, TemplateGroupResp.class));
                    }
                }
            }
            if (userCollectList.contains(items.getId())) {
                items.setCollected(true);
            }
        });
        return result;
    }

    @Override
    public List<TemplateResp> getTemplateList() {
        List<TemplateResp> list = SmartPageUtil.convert(this.list(), TemplateResp.class);
        // 获取模板类型
        // 获取所有的模板类型MAP
        List<TypeResp> typeList = SmartPageUtil.convert(this.typeService.list(), TypeResp.class);
        // typeList to map
        Map<Long, TypeResp> typeMap = typeList.stream().collect(Collectors.toMap(TypeResp::getId, Function.identity()));
        list.forEach(items -> {
            items.setBlockType(typeMap.get(items.getBlockTypeId()));
        });
        return list;
    }

    void checkRequestParam(TemplateReq req) {
        // 检查模板类型是否存在
        this.typeService.findById(req.getBlockTypeId());
        // 检查模板风格是否存在 对应 req.getStyleIds().size() 长度
        if (!CollectionUtils.isEmpty(req.getStyleIds())) {
            List<Style> styles = this.styleService.listByIds(req.getStyleIds());
            if (styles.size() != req.getStyleIds().size()) {
                throw new RuntimeException("模板风格信息有误~");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public Boolean saveTemplate(TemplateReq req) {
        // 检查参数
        this.checkRequestParam(req);
        // 入库
        Template template = new Template();
        BeanUtils.copyProperties(req, template);
        this.save(template);
        // save template_style
        this.templateStyleService.batchSave(template.getId(), req.getStyleIds());
        return true;
    }

    @Override
    public Boolean editTemplate(long id, TemplateReq req) {
        // 检查参数
        this.checkRequestParam(req);
        // 判断是否存在
        Template template = this.findById(id);
        // 修改
        BeanUtils.copyProperties(req, template);
        this.updateById(template);
        // 先删除掉这个模板的所有风格对应关系
        this.templateStyleService.removeByTemplateId(id);
        // save template_style
        this.templateStyleService.batchSave(template.getId(), req.getStyleIds());
        return true;
    }

    @Override
    public Boolean delTemplate(long id) {
        // 判断是否存在
        Template template = this.findById(id);
        // 删除template
        this.removeById(template);
        // 删除template_style
        this.templateStyleService.removeByTemplateId(id);
        return true;
    }

    @Override
    public Boolean collect(long id) {
        return true;
    }
}
